﻿using Alphacat.Model;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Web;
using System.IO;
using Newtonsoft.Json;

namespace AlphaCat.View
{
    public partial class MainForm : Form
    {
        Timer timer;
        WXService wxs;

        //支持的文件类型
        string[] Supported_File_Type = {
                "doc", "docx",
                "ppt", "pptx",
                "xls", "xlsx",
                "txt", "pdf"
        };

        List<FileTask> waitingFileQueue;

        int maxFileWorkingNum = 2; // 同时工作数
        List<BackgroundWorker> doingFileQueue;
        

        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            timeLabel.Text = "现在是: " + DateTime.Now.ToString();
            timer = new Timer();
            timer.Interval = 1000;
            timer.Tick += Timer_Tick;
            timer.Start();

            doingFileQueue = new List<BackgroundWorker>();
            waitingFileQueue = new List<FileTask>();
            doWXInit();
        }

        private void Timer_Tick(object sender, EventArgs e)
        {
            //throw new NotImplementedException();
            timeLabel.Text = "现在是: " + DateTime.Now.ToString();

        }
        
        private void doWXInit()
        {
            wxs = new WXService();
            ((Action)delegate ()
            {
                
                JObject init_result = wxs.WxInit();  //初始化

                if (init_result != null)
                {
                    this.BeginInvoke((Action)delegate ()
                    {
                        ACLog("登陆成功");
                        //ACLog(init_result.ToString());
                    });
                    
                }

                string sync_flag = "";
                JObject sync_result;
                while (true)
                {
                    sync_flag = wxs.WxSyncCheck();  //同步检查
                    /*
                    this.BeginInvoke((Action)delegate ()
                    {
                        ACLog("sync_flag:");
                        ACLog(sync_flag);
                    });
                    */
                    if (sync_flag == null)
                    {
                        continue;
                    }
                    //这里应该判断 sync_flag中selector的值
                    else //有消息
                    {
                        sync_result = wxs.WxSync();  //进行同步
                        if (sync_result != null)
                        {
                            if (sync_result["AddMsgCount"] != null && sync_result["AddMsgCount"].ToString() != "0")
                            {
                                foreach (JObject m in sync_result["AddMsgList"])
                                {
                                    
                                    string from = m["FromUserName"].ToString();
                                    string to = m["ToUserName"].ToString();
                                    string content = m["Content"].ToString();
                                    string type = m["MsgType"].ToString();
                                    if (type == "51")  //屏蔽一些系统数据
                                    {
                                        continue;
                                    }
                                    this.BeginInvoke((Action)delegate ()
                                    {
                                        //ACLog("type: "+type);
                                        switch (type)
                                        {
                                            case "1":
                                                ACLog("收到文本消息:\r\n发送方: " + from + "\r\n内容: " + content);
                                                //ACLog(m.ToString());
                                                autoReplyText(content, to, from);
                                                break;
                                            case "3":
                                                ACLog("收到图片消息:\r\n发送方: " + from);
                                                break;
                                            case "49":
                                                ACLog("收到文件消息:\r\n发送方: " + from+"\r\n文件名: "+ m["FileName"].ToString());
                                                //ACLog(m.ToString());
                                                handleFileMsg(m);
                                                break;
                                            default:
                                                ACLog("收到无关消息:\r\n发送方: " + from + "\r\n内容: " + content);
                                                break;
                                        }
                                        
                                    });

                                    /*
                                    WXMsg msg = new WXMsg();
                                    msg.From = from;
                                    msg.Msg = type == "1" ? content : "请在其他设备上查看消息";  //只接受文本消息
                                    msg.Readed = false;
                                    msg.Time = DateTime.Now;
                                    msg.To = to;
                                    msg.Type = int.Parse(type);
                                    */
                                    
                                }
                            }
                        }
                    }
                    System.Threading.Thread.Sleep(2000);
                    
                }
            }).BeginInvoke(null, null);
            
        }

        // 自动回复关键词 还未设置任何关键词
        private void autoReplyText(string msg, string me, string to)
        {
            
            ((Action)delegate ()
            {
                //string replyMsg = "您好，欢迎使用喵印，我是阿尔法猫。把文件发给我吧，然后我会给您文件二维码，给打印机扫一下，立刻就可以打印啦！";
                string replyMsg = "";
                switch (msg)
                {
                    case "测试回复":
                        replyMsg = "这是测试";
                        break;
                    case "二维码":
                        try
                        {
                            string docPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "/AlphaCat/code.png";
                            string res = BaseService.UploadFileWithPath(docPath, me, to);
                            this.BeginInvoke((Action)delegate ()
                            {
                                ACLog("上传code结果:\r\n" + res);
                            });
                            JObject uploadRes = JsonConvert.DeserializeObject(res) as JObject;
                            string mediaid = uploadRes["MediaId"].ToString();
                            wxs.SendImgMsg(mediaid, me, to);

                        }
                        catch
                        {
                            this.BeginInvoke((Action)delegate ()
                            {
                                ACLog("发送code失败");
                            });

                        }

                        break;
                    case "二维码连发":
                        for (int i = 0; i < 4; i++)
                        {
                            try
                            {
                                string docPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "/AlphaCat/code.png";
                                string res = BaseService.UploadFileWithPath(docPath, me, to);
                                this.BeginInvoke((Action)delegate ()
                                {
                                    ACLog("上传code结果" + i + ":\r\n" + res);
                                });
                                JObject uploadRes = JsonConvert.DeserializeObject(res) as JObject;
                                string mediaid = uploadRes["MediaId"].ToString();
                                wxs.SendImgMsg(mediaid, me, to);

                            }
                            catch
                            {
                                this.BeginInvoke((Action)delegate ()
                                {
                                    ACLog("发送code失败" + i);
                                });

                            }
                            System.Threading.Thread.Sleep(1000);
                        }
                        
                        break;
                    default:
                        break;
                }
                if (replyMsg != "")
                {
                    wxs.SendMsg(replyMsg, me, to, 1);
                }
                
            }).BeginInvoke(null, null);
            
            
            /*
            string docPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "/AlphaCat/code.png";
            ((Action)delegate ()
            {

                try
                {
                    //byte[] bytes = BaseService.FilePathUploadPost(docPath, me, to);
                    //string res = Encoding.UTF8.GetString(bytes);
                    string res = BaseService.UploadFileWithPath(docPath, me, to);
                    this.BeginInvoke((Action)delegate ()
                    {
                        ACLog("上传code结果:\r\n" + res);
                    });
                    JObject uploadRes = JsonConvert.DeserializeObject(res) as JObject;
                    string mediaid = uploadRes["MediaId"].ToString();
                    wxs.SendImgMsg(mediaid, me, to);

                }
                catch
                {
                    this.BeginInvoke((Action)delegate ()
                    {
                        ACLog("发送code失败");
                    });
                    
                }
            }).BeginInvoke(null, null);
            */

        }

        // 处理文件
        private void handleFileMsg(JObject msg)
        {
            string docPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "/AlphaCat/";
            docPath += DateTime.Now.ToString("yyyy-MM-dd");
            if (Directory.Exists(docPath) == false)//如果不存在就创建file文件夹
            {
                Directory.CreateDirectory(docPath);
            }
            string sender = msg["FromUserName"].ToString();
            string mediaid = msg["MediaId"].ToString();
            string filename = msg["FileName"].ToString();
            string msgid = msg["MsgId"].ToString();
            string me = msg["ToUserName"].ToString();

            string[] fileNameCompo = filename.Split('.'); // 分割文件名，获取文件类型
            string fileType = "";
            bool support = false;
            if (fileNameCompo.Length >= 2)
            {
                fileType = fileNameCompo.Last();
                foreach (string supportType in Supported_File_Type)
                {
                    if (fileType == supportType)
                    {
                        support = true;
                        break;
                    }
                }
            }
            if (!support) // 文件类型不支持
            {
                return;
            }
            string fromuser = BaseService.GetCookie("wxuin").Value;
            string passTicket = BaseService.PassTicket;
            string dataTicket = BaseService.GetCookie("webwx_data_ticket").Value;

            string fileUrl = "https://file.wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetmedia?";
            fileUrl += "sender=" + sender;
            fileUrl += "&mediaid=" + mediaid;
            fileUrl += "&filename=" + HttpUtility.UrlEncode(filename);
            fileUrl += "&fromuser=" + fromuser;
            fileUrl += "&passTicket=" + passTicket;
            fileUrl += "&dataTicket=" + dataTicket;
            //fileUrl = HttpUtility.UrlEncode(fileUrl, Encoding.GetEncoding("gbk"));

            string thisFileName = msgid + "." + fileType;
            docPath += "/" + thisFileName;
            ACLog("文件: " + fileUrl);

            BackgroundWorker bw = new BackgroundWorker();
            bw.DoWork += new DoWorkEventHandler(doFileTask);
            bw.WorkerReportsProgress = true;
            bw.RunWorkerCompleted += Bw_RunWorkerCompleted;
            bw.ProgressChanged += Bw_ProgressChanged;
            doingFileQueue.Add(bw);
            bw.RunWorkerAsync(new FileTask(fileUrl, thisFileName, sender, me, filename));
            taskList.Items.Add("下载 " + thisFileName);

            //if (doingFileQueue.Count < maxFileWorkingNum)
            //{
            //    BackgroundWorker bw = new BackgroundWorker();
            //    bw.DoWork += new DoWorkEventHandler(doFileTask);
            //    bw.WorkerReportsProgress = true;
            //    bw.RunWorkerCompleted += Bw_RunWorkerCompleted;
            //    bw.ProgressChanged += Bw_ProgressChanged;
            //    doingFileQueue.Add(bw);
            //    bw.RunWorkerAsync(new FileTask(fileUrl, docPath, thisFileName, sender, me, filename));
            //    taskList.Items.Add("下载 " + thisFileName);
            //}
            //else // 同时操作的文件到达最大数
            //{
                
            //    waitingFileQueue.Add(new FileTask(fileUrl, docPath, thisFileName, sender, me, filename));
            //    taskList.Items.Add("等待 " + thisFileName);
            //}

            taskCounter.Text = (doingFileQueue.Count + waitingFileQueue.Count).ToString();
            

            /*
            ((Action)delegate ()
            {
                bool downloadState = BaseService.downloadGetFile(fileUrl, docPath);

                this.BeginInvoke((Action)delegate ()
                {
                    if (downloadState)
                    {
                        ACLog("下载完成: " + thisFileName);
                    }
                    else
                    {
                        ACLog("下载失败: " + thisFileName);
                    }
                });

            }).BeginInvoke(null, null);
            */
        }

        private void Bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            int progress = e.ProgressPercentage;
            int index = doingFileQueue.IndexOf((BackgroundWorker)sender);
            string taskName = (string)taskList.Items[index];
            taskList.Items.RemoveAt(index);

            string status = "失联";
            switch (progress)
            {
                case 1:
                    status = "转换";
                    break;
                case 2:
                    status = "上传";
                    break;
                case 3:
                    status = "回复对方";
                    break;
                case 9:
                    status = "失败";
                    ACLog("下载失败: " + taskName);
                    break;

                case 92:
                    status = "失败";
                    ACLog("上传失败: " + taskName);
                    break;
                case 91:
                    status = "失败";
                    ACLog("回复失败: " + taskName);
                    break;
                default:
                    break;
            }
            taskList.Items.Insert(index, status + " " + taskName.Split(' ')[1]);
        }

        private void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            int index = doingFileQueue.IndexOf((BackgroundWorker)sender);
            doingFileQueue.Remove((BackgroundWorker)sender);
            //taskList.Items.RemoveAt(index);
            
            //while (doingFileQueue.Count < 5)
            //{
            //    if (waitingFileQueue.Count > 0)
            //    {
            //        FileTask fileTask = waitingFileQueue.First();
            //        waitingFileQueue.RemoveAt(0);
            //        BackgroundWorker bw = new BackgroundWorker();
            //        bw.DoWork += new DoWorkEventHandler(doFileTask);
            //        bw.WorkerReportsProgress = true;
            //        bw.RunWorkerCompleted += Bw_RunWorkerCompleted;
            //        doingFileQueue.Add(bw);
            //        bw.RunWorkerAsync(fileTask);

            //        //string taskName = (string)taskList.Items[doingFileQueue.Count];
            //        //taskList.Items.RemoveAt(doingFileQueue.Count);
            //        //taskList.Items.Insert(index, "下载 " + taskName.Split(' ')[1]);
            //    }
            //    else
            //    {
            //        break;
            //    }
            //}
            taskCounter.Text = (doingFileQueue.Count + waitingFileQueue.Count).ToString();
        }

        private void doFileTask(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker bw = (BackgroundWorker)sender;
            FileTask fileObj = (FileTask)e.Argument;
            string fileUrl = fileObj.Url;
            //string docPath = fileObj.Path;
            string filename = fileObj.FileName;
            string realFileName = fileObj.RealFileName;
            string from = fileObj.FromUserID;
            string me = fileObj.MyUserID;

            //bool downloadState = BaseService.downloadGetFile(fileUrl, docPath);
            byte[] filedata = BaseService.SendGetRequest(fileUrl);

            if (filedata != null)
            {
                bw.ReportProgress(1); // 下载完毕
                System.Threading.Thread.Sleep(1000);
                bw.ReportProgress(2); // 转换完毕
                //System.Threading.Thread.Sleep(1000);
                
                try
                {
                    

                    //string uploadRes = BaseService.UploadServer(docPath);

                    string uploadRes = BaseService.UploadServerWithBytes(filedata, filename);
                    Console.WriteLine("///////上传文件到服务器///////");
                    Console.WriteLine(uploadRes);
                    bw.ReportProgress(3); // 上传完毕

                    JObject uploadObj = JsonConvert.DeserializeObject(uploadRes) as JObject;
                    string status = uploadObj["status"].ToString();
                    if (status == "200")
                    {
                        string ornum = uploadObj["data"]["ornum"].ToString();
                        if (ornum != null)
                        {
                            //byte[] picData = QRCode.GetQRCode("123456");
                            byte[] picData = QRCode.GetQRCodeBytes(ornum);
                            
                            string res = BaseService.UploadFileWithBytes(picData, me, from);

                            //ACLog("上传code结果:\r\n" + res);
                            Console.WriteLine("上传code结果:\r\n" + res);

                            JObject sendRes = JsonConvert.DeserializeObject(res) as JObject;
                            string mediaid = sendRes["MediaId"].ToString();
                            wxs.SendImgMsg(mediaid, me, from);
                            System.Threading.Thread.Sleep(3000);
                            wxs.SendMsg("文件 " + realFileName + " 处理完成，请到打印终端扫码打印，有效期48小时。", me, from, 1);
                        }
                        else
                        {
                            //wxs.SendMsg("抱歉，文件 " + realFileName + " 处理出错，请稍后重试。", me, from, 1);
                        }
                    }
                    else
                    {
                        //wxs.SendMsg("抱歉，文件 " + realFileName + " 处理出错，请稍后重试。", me, from, 1);
                    }
                    
                    
                }
                catch
                {
                    //ACLog("回复二维码失败");
                    bw.ReportProgress(91);
                    //wxs.SendMsg("抱歉，文件\"" + realFileName + "\"处理出错，请稍后重试。", me, from, 1);
                }
                
            }
            else
            {
                bw.ReportProgress(9);
                //wxs.SendMsg("抱歉，文件\"" + realFileName + "\"处理出错，请稍后重试。", me, from, 1);

            }
        }

        private void ACLog(string str)
        {
            console.Text += DateTime.Now.ToString() + " " + str + "\r\n";
            console.SelectionStart = console.Text.Length;
            console.ScrollToCaret();
        }

        private void generateCodeBtn_Click(object sender, EventArgs e)
        {
            //QRCode.GetQRCodePngFile(qrcodeText.Text);
            QRCode.SaveBitmapPngFile(qrcodeText.Text);
        }

        private void testUploadBtn_Click(object sender, EventArgs e)
        {
            string docPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "/AlphaCat/code.png";
            //BaseService.FilePathUploadPost(docPath, ,);
        }

        private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            Environment.Exit(0);
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            
            if (doingFileQueue.Count > 0 || waitingFileQueue.Count > 0)
            {
                DialogResult res = MessageBox.Show("任务执行中，是否退出？", "退出", MessageBoxButtons.YesNo);
                if (res == DialogResult.Yes)
                {
                    e.Cancel = false;
                }
                else
                {
                    e.Cancel = true;
                }
            }
        }
    }
}
